package com.quocnv.mediascanner;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.http.conn.util.InetAddressUtils;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class ListIPActivity extends FragmentActivity implements
		OnItemClickListener
{
	private static final String TAG = "ListIPActivity";
	ListView lvIp;

	@Override
	protected void onCreate(Bundle arg0)
	{
		super.onCreate(arg0);
		setContentView(R.layout.activity_list_ip);

		lvIp = (ListView) findViewById(R.id.lvIp);
		lvIp.setOnItemClickListener(this);

		new ScanIPTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
				(Void) null);
	}

	@Override
	protected void onStart()
	{
		super.onStart();

	}

	private void checkListIp() throws IOException
	{
		// InetAddress localhost = InetAddress.getLocalHost();
		InetAddress localhost = InetAddress.getByName(getIPAddress(true));
		Log.e(TAG, "getLocalHost = " + localhost.toString());

		// WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
		// String strip = Formatter.formatIpAddress(wm.getConnectionInfo()
		// .getIpAddress());
		// Log.e(TAG, "getLocalHost = " + getIPAddress(true));

		byte[] ip = localhost.getAddress();
		// byte[] ip =
		// { 10, 0, 3, 15 };

		Log.e(TAG, "Scanning...");
		for (int i = 1; i <= 254; i++)
		{
			ip[3] = (byte) i;
			InetAddress address = InetAddress.getByAddress(ip);
			if (isReachable(address.getHostAddress(), 1000))
			{
				Log.e(TAG, address.toString());
			}
			else if (!address.getHostAddress().equals(address.getHostName()))
			{
				// machine is known in a DNS lookup
			}
			else
			{
				// the host address and host name are equal, meaning the host
				// name could not be resolved
			}
		}
		Log.e(TAG, "Finished");

	}

	public boolean isReachable(String addr, int timeout) throws IOException
	{
		Log.e(TAG, "run=" + addr);

		InetAddress inet = InetAddress.getByName(addr);
		String hardwareAddress = HardwareAddress.getHardwareAddress(addr);

		// Arp Check #1
		if (!HardwareAddress.NOMAC.equals(hardwareAddress))
		{
			Log.e(TAG, "found using arp #1 " + addr);
			return true;
		}

		// Native InetAddress check
		if (inet.isReachable(timeout))
		{
			Log.e(TAG, "found using InetAddress ping " + addr);
			return true;
		}

		// Arp Check #2
		hardwareAddress = HardwareAddress.getHardwareAddress(addr);
		if (!HardwareAddress.NOMAC.equals(hardwareAddress))
		{
			Log.e(TAG, "found using arp #2 " + addr);
			return true;
		}

		// Custom check
		Socket s = new Socket();
		for (int i = 0; i < HardwareAddress.DPORTS.length; i++)
		{
			try
			{
				s.bind(null);
				s.connect(
						new InetSocketAddress(addr, HardwareAddress.DPORTS[i]),
						timeout);
				Log.v(TAG, "found using TCP connect " + addr + " on port="
						+ HardwareAddress.DPORTS[i]);
			} catch (IOException e)
			{
			} catch (IllegalArgumentException e)
			{
			} finally
			{
				try
				{
					s.close();
				} catch (Exception e)
				{
				}
			}
		}

		return false;
	}

	public static String getIPAddress(boolean useIPv4)
	{
		try
		{
			List<NetworkInterface> interfaces = Collections
					.list(NetworkInterface.getNetworkInterfaces());
			for (NetworkInterface intf : interfaces)
			{
				List<InetAddress> addrs = Collections.list(intf
						.getInetAddresses());
				for (InetAddress addr : addrs)
				{
					if (!addr.isLoopbackAddress())
					{
						String sAddr = addr.getHostAddress().toUpperCase();
						boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
						if (useIPv4)
						{
							if (isIPv4)
								return sAddr;
						}
						else
						{
							if (!isIPv4)
							{
								int delim = sAddr.indexOf('%'); // drop ip6 port
																// suffix
								return delim < 0 ? sAddr : sAddr.substring(0,
										delim);
							}
						}
					}
				}
			}
		} catch (Exception ex)
		{
		} // for now eat exceptions
		return "";
	}

	private class ScanIPTask extends AsyncTask<Void, String, ArrayList<String>>
	{
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(
				getApplicationContext(), android.R.layout.simple_list_item_1);

		private ProgressDialog dialog = new ProgressDialog(ListIPActivity.this);

		@Override
		protected void onPreExecute()
		{
			lvIp.setAdapter(adapter);

			dialog.setCancelable(true);
			dialog.setMessage("Scanning...");
			dialog.setIndeterminate(true);
			dialog.show();
			super.onPreExecute();
		}

		@Override
		protected ArrayList<String> doInBackground(Void... arg0)
		{
			ArrayList<String> ips = new ArrayList<String>();
			try
			{
				// InetAddress localhost = InetAddress.getLocalHost();
				InetAddress localhost = null;

				localhost = InetAddress.getByName(getIPAddress(true));
				Log.e(TAG, "getLocalHost = " + localhost.toString());

				byte[] ip = localhost.getAddress();

				Log.e(TAG, "Scanning...");
				for (int i = 1; i <= 254; i++)
				{
					ip[3] = (byte) i;
					InetAddress address = InetAddress.getByAddress(ip);
					if (address.getHostAddress().equals(
							localhost.getHostAddress()))// my ip
						continue;

					if (isReachable(address.getHostAddress(), 100))
					{
						ips.add(address.getHostAddress());
						publishProgress(address.getHostAddress());

						Log.e(TAG, address.toString());
					}
					else if (!address.getHostAddress().equals(
							address.getHostName()))
					{
						// machine is known in a DNS lookup
					}
					else
					{
						// the host address and host name are equal, meaning the
						// host
						// name could not be resolved
					}
				}
				Log.e(TAG, "Finished");
			} catch (UnknownHostException e)
			{
				e.printStackTrace();
			} catch (IOException e)
			{
				e.printStackTrace();
			}
			return ips;
		}

		@Override
		protected void onProgressUpdate(String... values)
		{
			adapter.addAll(values);
			adapter.notifyDataSetChanged();
			super.onProgressUpdate(values);
		}

		@Override
		protected void onPostExecute(ArrayList<String> result)
		{
			super.onPostExecute(result);
			if (this.dialog.isShowing())
				this.dialog.dismiss();

			if (result != null && result.size() != 0)
			{
				adapter.clear();
				adapter.addAll(result);
				adapter.notifyDataSetChanged();
			}
			else
				Toast.makeText(getApplicationContext(),
						"Không tìm thấy IP nào", Toast.LENGTH_LONG).show();
		}
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View arg1, int position,
			long id)
	{
		String item = (String) parent.getItemAtPosition(position);
		Intent i = new Intent(this, ShowSmbFileActivity.class);
		i.putExtra("path", item);
		startActivity(i);
	}
}
